package com.team.childapp.view;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;


import java.io.File;

import androidx.annotation.Nullable;

import com.team.childapp.R;

public class DashboardView extends View {

    private static final String empty = "";

    private Paint mPaint;
    private Path mIndicatorPath;
    private RectF mTagRectF;

    private int mViewWidth, mViewHeight;
    private float mCx, mCy;
    private RectF mDashboardActualRect;
    private RectF mSignalTopActualRect;
    private RectF mSignalLeftActualRect;
    private RectF mSignalRightActualRect;
    private RectF mBandIconActualRect;
    private RectF mIndicatorIconActualRect;

    private int mValue = 0;
    private boolean mShowSignalTopIcon = false;
    private boolean mShowSignalLeftIcon = false;
    private boolean mShowSignalRightIcon = false;
    private boolean mShowBandIcon = true;
    private ValueAnimator mValueAnim;
    private boolean isAnimating;

    private Drawable dashboardDrawable;
    private Bitmap dashboardBitmap;
    private Drawable signalTopDrawable;
    private Bitmap signalTopBitmap;
    private Drawable signalLeftDrawable;
    private Bitmap signalLeftBitmap;
    private Drawable signalRightDrawable;
    private Bitmap signalRightBitmap;
    private Drawable bandIconDrawable;
    private Bitmap bandIconBitmap;
    private Drawable indicatorDrawable;
    private Bitmap indicatorBitmap;
    private int dashboardWidth = 100;
    private int dashboardHeight = 100;
    private int signalIconWidth = 50;
    private int signalIconHeight = 50;
    private int bandIconDrawableWidth = 117;
    private int bandIconDrawableHeight = 37;
    private int bandIconDrawableDistance = 170;
    private float signalIconDistanceRate = 0.3f;
    private int indicatorDrawableWidth = 10;
    private int indicatorDrawableHeight = 80;
    private float centerOffsetXRate = 0.5f;
    private float centerOffsetYRate = 0.5f;
    private String unitText;
    private int unitTextSize = 28;
    private int unitTextColor = Color.WHITE;
    private int tagCount = 7;
    private int dividerCount = 8;
    private int tagTextSize = 28;
    private int tagTextColor = Color.WHITE;
    private int tagTextAlarmColor = Color.RED;
    private int indicatorTagWidth = 6;
    private int indicatorTagHeight = 28;
    private int indicatorTagDistance = 204;
    private int indicatorDividerWidth = 2;
    private int indicatorDividerHeight = 14;
    private int indicatorTagDividerDistance = 196;
    private int indicatorStartAngle = 135;
    private int indicatorSweepAngle = 270;
    private int indicatorWidth = 11;
    private int indicatorHeight = 158;
    private int indicatorStartColor = Color.RED;
    private int indicatorEndColor = Color.RED;
    private int minValue = 0;
    private int maxValue = 3000;
    private float valueDisplayRate = 0.01f;
    private int indicatorAnimDuration = 2000;

    public DashboardView(Context context) {
        this(context, null);
    }

    public DashboardView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public DashboardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public DashboardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs, defStyleAttr, defStyleRes);
    }

    private void initAttrs(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DashboardView, defStyleAttr, defStyleRes);
        dashboardDrawable = ta.getDrawable(R.styleable.DashboardView_dashboardDrawable);
        dashboardWidth = ta.getDimensionPixelSize(R.styleable.DashboardView_dashboardDrawableWidth, dashboardWidth);
        dashboardHeight = ta.getDimensionPixelSize(R.styleable.DashboardView_dashboardDrawableHeight, dashboardHeight);
        signalTopDrawable = ta.getDrawable(R.styleable.DashboardView_signalTopDrawable);
        signalLeftDrawable = ta.getDrawable(R.styleable.DashboardView_signalLeftDrawable);
        signalRightDrawable = ta.getDrawable(R.styleable.DashboardView_signalRightDrawable);
        signalIconWidth = ta.getDimensionPixelSize(R.styleable.DashboardView_signalIconWidth, signalIconWidth);
        signalIconHeight = ta.getDimensionPixelSize(R.styleable.DashboardView_signalIconHeight, signalIconHeight);
        bandIconDrawable = ta.getDrawable(R.styleable.DashboardView_bandIconDrawable);
        bandIconDrawableWidth = ta.getDimensionPixelSize(R.styleable.DashboardView_bandIconDrawableWidth, bandIconDrawableWidth);
        bandIconDrawableHeight = ta.getDimensionPixelSize(R.styleable.DashboardView_bandIconDrawableHeight, bandIconDrawableHeight);
        bandIconDrawableDistance = ta.getDimensionPixelSize(R.styleable.DashboardView_bandIconDrawableDistance, bandIconDrawableDistance);
        indicatorDrawable = ta.getDrawable(R.styleable.DashboardView_indicatorDrawable);
        indicatorDrawableWidth = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorDrawableWidth, indicatorDrawableWidth);
        indicatorDrawableHeight = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorDrawableHeight, indicatorDrawableHeight);
        signalIconDistanceRate = ta.getFloat(R.styleable.DashboardView_signalIconDistanceRate, signalIconDistanceRate);
        centerOffsetXRate = ta.getFloat(R.styleable.DashboardView_centerOffsetXRate, centerOffsetXRate);
        centerOffsetYRate = ta.getFloat(R.styleable.DashboardView_centerOffsetYRate, centerOffsetYRate);
        unitText = ta.getString(R.styleable.DashboardView_unitText);
        unitTextSize = ta.getDimensionPixelSize(R.styleable.DashboardView_unitTextSize, unitTextSize);
        unitTextColor = ta.getColor(R.styleable.DashboardView_unitTextColor, unitTextColor);
        tagCount = ta.getInteger(R.styleable.DashboardView_indicatorTagCount, tagCount);
        dividerCount = ta.getInteger(R.styleable.DashboardView_indicatorTagDividerCount, dividerCount);
        tagTextSize = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorTagTextSize, tagTextSize);
        tagTextColor = ta.getColor(R.styleable.DashboardView_indicatorTagTextColor, tagTextColor);
        tagTextAlarmColor = ta.getColor(R.styleable.DashboardView_indicatorTagTextAlarmColor, tagTextAlarmColor);
        indicatorTagWidth = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorTagWidth, indicatorTagWidth);
        indicatorTagHeight = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorTagHeight, indicatorTagHeight);
        indicatorTagDistance = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorTagDistance, indicatorTagDistance);
        indicatorDividerWidth = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorTagDividerWidth, indicatorDividerWidth);
        indicatorDividerHeight = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorTagDividerHeight, indicatorDividerHeight);
        indicatorTagDividerDistance = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorTagDividerDistance, indicatorTagDividerDistance);
        indicatorStartAngle = ta.getInteger(R.styleable.DashboardView_indicatorStartAngle, indicatorStartAngle);
        indicatorSweepAngle = ta.getInteger(R.styleable.DashboardView_indicatorSweepAngle, indicatorSweepAngle);
        indicatorWidth = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorWidth, indicatorWidth);
        indicatorHeight = ta.getDimensionPixelSize(R.styleable.DashboardView_indicatorHeight, indicatorHeight);
        indicatorStartColor = ta.getColor(R.styleable.DashboardView_indicatorStartColor, indicatorStartColor);
        indicatorEndColor = ta.getColor(R.styleable.DashboardView_indicatorEndColor, indicatorEndColor);
        indicatorAnimDuration = ta.getInteger(R.styleable.DashboardView_indicatorAnimDuration, indicatorAnimDuration);
        minValue = ta.getInteger(R.styleable.DashboardView_minValue, minValue);
        maxValue = ta.getInteger(R.styleable.DashboardView_maxValue, maxValue);
        valueDisplayRate = ta.getFloat(R.styleable.DashboardView_valueDisplayRate, valueDisplayRate);

        ta.recycle();
    }

    private void init(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        initAttrs(context, attrs, defStyleAttr, defStyleRes);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mIndicatorPath = new Path();
        mTagRectF = new RectF();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        getViewParams();
        prepareBitmaps();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawDashboardBackgroundAndSignalIcon(canvas);

        drawDashboardUnitText(canvas);

        drawIndicatorAndTags(canvas);

        drawIndicator(canvas);

    }

    private void getViewParams() {
        mViewWidth = getMeasuredWidth();
        mViewHeight = getMeasuredHeight();
        mCx = mViewWidth * centerOffsetXRate;
        mCy = mViewHeight * centerOffsetYRate;
    }

    private int getSafeTagCount() {
        return Math.max(2, tagCount);
    }

    private void prepareBitmaps() {
        if (dashboardDrawable instanceof BitmapDrawable) {
            dashboardBitmap = ((BitmapDrawable) dashboardDrawable).getBitmap();
            int bWidth = dashboardBitmap.getWidth();
            int bHeight = dashboardBitmap.getHeight();
            if (!checkBitmap(dashboardBitmap)) {
                dashboardBitmap = null;
                return;
            }
            int dashboardActualWidth = Math.min(bWidth, mViewWidth);
            int dashboardActualHeight = Math.min(bHeight, mViewHeight);
            float bRate = bWidth * 1f / bHeight;
            float tRate = dashboardActualWidth * 1f / bHeight;
            if (tRate > bRate) {
                dashboardActualWidth = ((int) (dashboardActualHeight * bRate));
            } else if (tRate < bRate) {
                dashboardActualHeight = ((int) (dashboardActualWidth / bRate));
            }
            if (mDashboardActualRect == null) {
                float cx = mViewWidth / 2f;
                float cy = mViewHeight / 2f;
                float hw = dashboardActualWidth / 2f;
                float hh = dashboardActualHeight / 2f;
                float left = cx - hw;
                float top = cy - hh;
                float right = cx + hw;
                float bottom = cy + hh;
                mDashboardActualRect = new RectF(left, top, right, bottom);
            }
            dashboardBitmap = Bitmap.createScaledBitmap(dashboardBitmap,
                    dashboardActualWidth, dashboardActualHeight, true);
        }
        int signalIconOffset = getSignalIconOffset();
        if (signalTopDrawable instanceof BitmapDrawable) {
            signalTopBitmap = ((BitmapDrawable) signalTopDrawable).getBitmap();
            if (!checkBitmap(signalTopBitmap, signalIconWidth, signalIconHeight)) {
                signalTopBitmap = null;
                return;
            }
            mSignalTopActualRect = getIconRectF(signalTopBitmap);
            mSignalTopActualRect.top = mSignalTopActualRect.top - signalIconOffset;
            mSignalTopActualRect.bottom = mSignalTopActualRect.bottom - signalIconOffset;
            signalTopBitmap = getIconBitmap(signalTopBitmap, mSignalTopActualRect);
        }
        if (signalLeftDrawable instanceof BitmapDrawable) {
            signalLeftBitmap = ((BitmapDrawable) signalLeftDrawable).getBitmap();
            if (!checkBitmap(signalLeftBitmap, signalIconWidth, signalIconHeight)) {
                signalLeftBitmap = null;
                return;
            }
            mSignalLeftActualRect = getIconRectF(signalLeftBitmap);
            mSignalLeftActualRect.left = mSignalLeftActualRect.left - signalIconOffset;
            mSignalLeftActualRect.right = mSignalLeftActualRect.right - signalIconOffset;
            signalLeftBitmap = getIconBitmap(signalLeftBitmap, mSignalLeftActualRect);
        }
        if (signalRightDrawable instanceof BitmapDrawable) {
            signalRightBitmap = ((BitmapDrawable) signalRightDrawable).getBitmap();
            if (!checkBitmap(signalRightBitmap, signalIconWidth, signalIconHeight)) {
                signalRightBitmap = null;
                return;
            }
            mSignalRightActualRect = getIconRectF(signalRightBitmap);
            mSignalRightActualRect.left = mSignalRightActualRect.left + signalIconOffset;
            mSignalRightActualRect.right = mSignalRightActualRect.right + signalIconOffset;
            signalRightBitmap = getIconBitmap(signalRightBitmap, mSignalRightActualRect);
        }
        if (bandIconBitmap == null && bandIconDrawable instanceof BitmapDrawable) {
            bandIconBitmap = ((BitmapDrawable) bandIconDrawable).getBitmap();
        }
        if (bandIconBitmap != null) {
            if (!checkBitmap(bandIconBitmap, bandIconDrawableWidth, bandIconDrawableHeight)) {
                bandIconBitmap = null;
                return;
            }
            mBandIconActualRect = getBandIconRectF(bandIconBitmap);
            mBandIconActualRect.top = mBandIconActualRect.top + bandIconDrawableDistance;
            mBandIconActualRect.bottom = mBandIconActualRect.bottom + bandIconDrawableDistance;
            bandIconBitmap = getIconBitmap(bandIconBitmap, mBandIconActualRect);
        }
        if (indicatorDrawable instanceof BitmapDrawable) {
            indicatorBitmap = ((BitmapDrawable) indicatorDrawable).getBitmap();
        }
        if (indicatorBitmap != null) {
            if (!checkBitmap(indicatorBitmap, indicatorDrawableWidth, indicatorDrawableHeight)) {
                indicatorBitmap = null;
                return;
            }
            mIndicatorIconActualRect = getIconRectF(indicatorBitmap);
        }
    }

    private RectF getIconRectF(Bitmap bitmap) {
        return getBitmapRectF(bitmap, signalIconWidth, signalIconHeight);
    }

    private RectF getBandIconRectF(Bitmap bitmap) {
        return getBitmapRectF(bitmap, bandIconDrawableWidth, bandIconDrawableHeight);
    }

    private RectF getBitmapRectF(Bitmap bitmap, int w, int h) {
        int bWidth = bitmap.getWidth();
        int bHeight = bitmap.getHeight();
        int iconActualWidth = Math.min(bWidth, w);
        int iconActualHeight = Math.min(bHeight, h);
        float bRate = bWidth * 1f / bHeight;
        float tRate = w * 1f / h;
        if (tRate > bRate) {
            iconActualWidth = ((int) (iconActualHeight * bRate));
        } else if (tRate < bRate) {
            iconActualHeight = ((int) (iconActualWidth / bRate));
        }
        float hw = iconActualWidth / 2f;
        float hh = iconActualHeight / 2f;
        float left = mCx - hw;
        float top = mCy - hh;
        float right = mCx + hw;
        float bottom = mCy + hh;
        return new RectF(left, top, right, bottom);
    }

    private Bitmap getIconBitmap(Bitmap bitmap, RectF rectF) {
        int iconActualWidth = ((int) (rectF.right - rectF.left));
        int iconActualHeight = ((int) (rectF.bottom - rectF.top));
        return Bitmap.createScaledBitmap(bitmap, iconActualWidth, iconActualHeight, true);
    }

    private int getSignalIconOffset() {
        int r = ((int) (Math.min(mViewWidth, mViewHeight) / 2f));
        if (mDashboardActualRect != null) {
            float width = mDashboardActualRect.right - mDashboardActualRect.left;
            float height = mDashboardActualRect.bottom - mDashboardActualRect.top;
            r = ((int) (Math.min(width, height) / 2f));
        }
        return ((int) (signalIconDistanceRate * r));
    }

    private boolean checkBitmap(Bitmap bitmap) {
        return checkBitmap(bitmap, 1, 1);
    }

    private boolean checkBitmap(Bitmap bitmap, int bw, int bh) {
        return checkBitmap(bitmap, mViewWidth, mViewHeight, bw, bh);
    }

    private boolean checkBitmap(Bitmap bitmap, int vw, int vh, int bw, int bh) {
        boolean pass = bitmap != null && bitmap.getWidth() != 0 && bitmap.getHeight() != 0
                && vw != 0 && vh != 0 && bw != 0 && bh != 0;
        if (!pass && bitmap != null) {
            bitmap.recycle();
        }
        return pass;
    }

    private void drawDashboardBackgroundAndSignalIcon(Canvas canvas) {
        int showAlpha = 255;
        int hideAlpha = 75;
        if (dashboardBitmap != null && mDashboardActualRect != null) {
            canvas.drawBitmap(dashboardBitmap, mDashboardActualRect.left, mDashboardActualRect.top, mPaint);
        }
        if (signalTopBitmap != null && mSignalTopActualRect != null) {
            mPaint.setAlpha(mShowSignalTopIcon ? showAlpha : hideAlpha);
            canvas.drawBitmap(signalTopBitmap, mSignalTopActualRect.left, mSignalTopActualRect.top, mPaint);
        }
        if (signalLeftBitmap != null && mSignalLeftActualRect != null) {
            mPaint.setAlpha(mShowSignalLeftIcon ? showAlpha : hideAlpha);
            canvas.drawBitmap(signalLeftBitmap, mSignalLeftActualRect.left, mSignalLeftActualRect.top, mPaint);
        }
        if (signalRightBitmap != null && mSignalRightActualRect != null) {
            mPaint.setAlpha(mShowSignalRightIcon ? showAlpha : hideAlpha);
            canvas.drawBitmap(signalRightBitmap, mSignalRightActualRect.left, mSignalRightActualRect.top, mPaint);
        }
        mPaint.setAlpha(showAlpha);
        if (bandIconBitmap != null && mBandIconActualRect != null && mShowBandIcon) {
            canvas.drawBitmap(bandIconBitmap, mBandIconActualRect.left, mBandIconActualRect.top, mPaint);
        }
    }

    private void drawDashboardUnitText(Canvas canvas) {
        mPaint.setColor(tagTextColor);
        mPaint.setTextSize(unitTextSize);
        float ex = mCx;
        float ey = mCy + mCy / 2.1f;
        String unitTag = unitText == null ? empty : unitText;
        drawTagText(canvas, ex, ey, unitTag);
    }

    private void drawIndicatorAndTags(Canvas canvas) {
        float dAngle = indicatorStartAngle;
        int tagCount = getSafeTagCount();
        int stepCount = Math.max(1, (dividerCount + 1) * (tagCount - 1));
        float stepAngle = indicatorSweepAngle * 1f / stepCount;
        int sIndex = tagCount - 1;
        for (int i = 0; i < sIndex; i++) {
            if (i == tagCount - 2 || i == tagCount - 1) {
                mPaint.setColor(tagTextAlarmColor);
            } else {
                mPaint.setColor(tagTextColor);
            }
            drawIndicatorAndTag(canvas, dAngle, true, i);
            dAngle += stepAngle;
            for (int j = 0; j < dividerCount; j++) {
                drawIndicatorAndTag(canvas, dAngle, false, 0);
                dAngle += stepAngle;
            }
            if (i == sIndex - 1) {
                drawIndicatorAndTag(canvas, dAngle, true, i + 1);
            }
        }
    }

    private void drawIndicatorAndTag(Canvas canvas, float dAngle, boolean haveTag, int tagIndex) {
        double angle = Math.toRadians(dAngle);
        double cos = Math.cos(angle);
        double sin = Math.sin(angle);
        if (haveTag) {
            mPaint.setStrokeWidth(indicatorTagWidth);
            float sx = ((float) (cos * indicatorTagDistance)) + mCx;
            float sy = ((float) (sin * indicatorTagDistance)) + mCy;
            float ex = ((float) (cos * (indicatorTagDistance - indicatorTagHeight))) + mCx;
            float ey = ((float) (sin * (indicatorTagDistance - indicatorTagHeight))) + mCy;
            canvas.drawLine(sx, sy, ex, ey, mPaint);
            int tagCount = getSafeTagCount();
            int stepValue = (maxValue - minValue) / (tagCount - 1);
            int value = minValue + stepValue * tagIndex;
            String displayTag = String.valueOf((int) (value * valueDisplayRate));
            mPaint.setTextSize(tagTextSize);
            drawTagText(canvas, ex, ey, displayTag);
        } else {
            mPaint.setStrokeWidth(indicatorDividerWidth);
            float sx = ((float) (cos * indicatorTagDividerDistance)) + mCx;
            float sy = ((float) (sin * indicatorTagDividerDistance)) + mCy;
            float ex = ((float) (cos * (indicatorTagDividerDistance - indicatorDividerHeight))) + mCx;
            float ey = ((float) (sin * (indicatorTagDividerDistance - indicatorDividerHeight))) + mCy;
            canvas.drawLine(sx, sy, ex, ey, mPaint);
        }
    }

    private void drawTagText(Canvas canvas, float ex, float ey, String tag) {
        float th = tagTextSize;
        float tw = mPaint.measureText(tag);
        float rx = ex - mCx;
        float ry = ey - mCy;
        if (rx > 0) {
            mTagRectF.left = ex - tw;
            if (ry > 0) {
                mTagRectF.top = ey - th;
            } else if (ry < 0) {
                mTagRectF.top = ey;
            } else {
                mTagRectF.top = ey - th / 2;
                mTagRectF.left = ex - tw / 8.5f * 10;
            }
        } else if (rx < 0) {
            mTagRectF.left = ex;
            if (ry > 0) {
                mTagRectF.top = ey - th;
            } else if (ry < 0) {
                mTagRectF.top = ey;
            } else {
                mTagRectF.top = ey - th / 2;
                mTagRectF.left = ex + tw / 8.5f;
            }
        } else {
            mTagRectF.left = ex - tw / 2;
            if (ry > 0) {
                mTagRectF.top = ey + th;
            } else {
                mTagRectF.top = ey;
            }
        }
        mTagRectF.right = mTagRectF.left + tw;
        mTagRectF.bottom = mTagRectF.top + th;
        mPaint.setTextAlign(Paint.Align.CENTER);
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
        float baseline = mTagRectF.centerY() + distance;
        canvas.drawText(tag, mTagRectF.centerX(), baseline, mPaint);
    }

    private void drawIndicator(Canvas canvas) {
        float dAngle = getIndicatorAngle();
        float dAngle0 = dAngle + 90;
        float dAngle2 = dAngle0 + 90;
        float dAngle3 = dAngle - 90;
        double angle = Math.toRadians(dAngle);
        double angle0 = Math.toRadians(dAngle0);
        double angle2 = Math.toRadians(dAngle2);
        double angle3 = Math.toRadians(dAngle3);
        float hw = indicatorWidth / 2f;
        //顶点
        float sx = ((float) (Math.cos(angle) * indicatorHeight)) + mCx;
        float sy = ((float) (Math.sin(angle) * indicatorHeight)) + mCy;
        //角点0
        float sx0 = ((float) (Math.cos(angle0) * hw)) + mCx;
        float sy0 = ((float) (Math.sin(angle0) * hw)) + mCy;
        //末点
        float sx2 = ((float) (Math.cos(angle2) * hw)) + mCx;
        float sy2 = ((float) (Math.sin(angle2) * hw)) + mCy;
        //角点1
        float sx3 = ((float) (Math.cos(angle3) * hw)) + mCx;
        float sy3 = ((float) (Math.sin(angle3) * hw)) + mCy;
        mPaint.setStrokeWidth(indicatorWidth);
        mPaint.setColor(indicatorStartColor);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        canvas.drawPoint(mCx, mCy, mPaint);
        mIndicatorPath.reset();
        mIndicatorPath.moveTo(sx, sy);
        mIndicatorPath.lineTo(sx0, sy0);
        mIndicatorPath.lineTo(sx3, sy3);
        mIndicatorPath.lineTo(sx, sy);
        mIndicatorPath.close();
        Shader indicatorShader = new LinearGradient(sx, sy, sx2, sy2,
                indicatorStartColor, indicatorEndColor, Shader.TileMode.REPEAT);
        mPaint.setShader(indicatorShader);
        canvas.drawPath(mIndicatorPath, mPaint);
        mPaint.setShader(null);
        mPaint.setStrokeCap(Paint.Cap.SQUARE);
    }

    private void drawIndicatorDrawable(Canvas canvas) {

    }

    private float getIndicatorAngle() {
        float rate = (mValue - minValue) * 1f / (maxValue - minValue);
        return indicatorStartAngle + indicatorSweepAngle * rate;
    }

    public void setValueWithAnim(int value) {
        if (isAnimating) {
            return;
        }
        if (mValueAnim != null) {
            mValueAnim.cancel();
        }
        if (value > maxValue) {
            value = maxValue;
        }
        if (value < minValue) {
            value = minValue;
        }
        isAnimating = true;
        mValueAnim = ValueAnimator.ofInt(mValue, value);
        mValueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int v = (int) animation.getAnimatedValue();
                setValue(v);
            }
        });
        mValueAnim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isAnimating = false;
            }
        });
        int duration = ((int) (Math.abs(value - mValue) * 1f / (maxValue - minValue) * indicatorAnimDuration));
        mValueAnim.setInterpolator(new AccelerateDecelerateInterpolator());
        mValueAnim.setDuration(duration);
        mValueAnim.start();
    }

    public void setValue(int value) {
        if (value > maxValue) {
            value = maxValue;
        }
        if (value < minValue) {
            value = minValue;
        }
        mValue = value;
        postInvalidate();
    }

    public int getValue() {
        return mValue;
    }

    public void showSignalTopIcon(boolean show) {
        if (mShowSignalTopIcon == show) {
            return;
        }
        mShowSignalTopIcon = show;
        postInvalidate();
    }

    public void showSignalLeftIcon(boolean show) {
        if (mShowSignalLeftIcon == show) {
            return;
        }
        mShowSignalLeftIcon = show;
        postInvalidate();
    }

    public void showSignalRightIcon(boolean show) {
        if (mShowSignalRightIcon == show) {
            return;
        }
        mShowSignalRightIcon = show;
        postInvalidate();
    }

    public void showBandIcon(boolean show) {
        if (mShowBandIcon == show) {
            return;
        }
        mShowBandIcon = show;
        postInvalidate();
    }

    public void loadBrandIcon(File iconFile) {
        if (iconFile == null || !iconFile.exists()) return;
        try {
            bandIconBitmap = BitmapFactory.decodeFile(iconFile.getAbsolutePath());
        } catch (Exception ignore) {
        }
    }

}
